Kubernetes v1.33 - Octarine

노트 속성
created 2025-04-25 11:32
is-folder false
aliases 쿠버네티스 옥타린
related 버전
index 3
webaddress https://kubernetes.io/blog/2025/04/23/kubernetes-v1-33-release/

개요


1.33의 테마는 옥타린: 마법의 색깔(Octarine: The Color of Magic)이다.
이 환상 테마의 기반은 Discworld라는 한 판타지 세계관이다.[1]
여기에서 옥타린은 마법사들에게만 보이는 신비의 8번째 색깔(무지개 색의 일부인 듯)을 지칭하는 표현인데, iptables 룰을 너무 오랫 동안 바라본 엔지니어 현자들도 볼 수 있다고 한다..
로고에 초록 드래곤이 이 세계관에서 유명한 놈인가 본데, 나는 잘 모르겠다.

아무튼 쿠버네티스 생태계가 활성화시키는 오픈소스 마법(고도로 발전된 기술은 마법과 구별할 수 없다..!)을 강조하기 위해 버전 명으로 선택됐다.
쿠버네티스가 10년을 넘기며 새로운 시기에 진입함에 따라 오픈소스 메인테이너, 컨트리뷰터들을 환영하기 위한 차원에서 1.33에서는 마법을 강조한다.
쿠버네티스의 코드 기반을 익히고 있더라도 한 걸음 뒤로 물러나 버전 릴리스 주기을 바라보면, 여전히 쿠버네티스는 마법처럼 느껴질 것이라는 게 주 골자.
(나도 쿠버 코드를 간혹 들여다보긴 하지만, 아직 릴리스할 때 어떤 과정을 거쳐서 반영되는지 구체적으로 모르겠다.)

핵심 업데이트

이번 1.33 버전에서는 18개의 Stable, 20개의 베타, 24개의 알파 기능이 추가됐고, 2개의 기능이 지원 중단(deprecated)된다.
그 중 주목할 만한 업데이트를 먼저 간략하게 다루자면,

스테이블로 전환되는 기능

Indexed Job에 대해 인덱스별로 backoff 제한을 설정할 수 있는 기능이 정식으로 도입되었다.
참고로 인덱싱 잡은 잡 스펙에 .spec.compltionMode=Indexed를 세팅한 잡을 말한다.
이는 잡의 성공 횟수에 각각 인덱스를 부여하고, 이 인덱스 별로 파드의 성공을 구분해 카운팅하는 방식으로 동작한다.
기존에는 잡에 backoffLimit 필드를 통해 잡의 재시도 횟수를 전체 실패를 고려해서 세팅해야만 했다.
그러나 이제는 인덱스 별로 재시도 횟수를 조절할 수 있게 되어 동작을 조금 더 세밀하게 제어할 수 있다.
그래서 특정 인덱스에서의 실패가 전체 잡을 종료시키는 일을 방지하고 다른 인덱스는 독립적으로 진행될 수 있도록 한다.

관련 스펙은 backoffLimetPerIndex에 간략하게 정리했다.

.spec.successPolicy를 사용해서 잡의 어떤 인덱스가 성공해야 하고(succeededIndexes), 얼마나 많은 파드가 성공해야 하는지(succeededCount{}) 지정할 수 있다.
부분적인 성공만으로 전체 성공을 확정지어도 되거나, 리더-워커 패턴에서 리더의 성공으로 잡의 성공을 결정지어도 되는 상황에서 유용할 것으로 생각된다.

서비스 어카운트 토큰 바인딩 보안 향상
서비스어카운트 토큰에 JTI와 노드에 대한 정보가 추가적으로 들어간다.
JTI(JWT ID)는 토큰의 클레임 필드 중 하나로, JWT 토큰마다 고유한 식별자이다.[2]

  "kubernetes.io": {
    "namespace": "my-namespace",
    "serviceaccount": {
      "name": "my-serviceaccount",
      "uid": "14ee3fa4-a7e2-420f-9f9a-dbc4507c3798"
    },
	# 노드와 파드 정보는 이 토큰이 파드에 마운팅됐을 때만 들어간다.
    "node": {
      "name": "my-node",
      "uid": "646e7c5e-32d6-4d42-9dbd-e504e6cbe6b1"
    },
    "pod": {
      "name": "my-pod",
      "uid": "5e0bd49b-f040-43b0-99b7-22765a53f7f3"
    },

jwt 토큰 클레임 필드에 이런 식으로 노드에 정보도 추가된다.
이를 통해 네임스페이스 별로 노드를 분리하거나, 특정 노드만 활용하는 워크로드의 토큰에 대해 조금 더 정밀한 검증을 할 수 있다.
아직 공식 문서로 반영된 것 같지는 않지만 아예 노드에 서비스 어카운트 토큰을 바인딩해서 노드의 라이프사이클을 따르도록 하는 방식도 가능해졌다.
이는 특정 노드에서만 토큰을 사용할 수 있도록 제한하여 토큰 오용 및 잠재적인 보안 침해의 위험을 줄일 수 있다.

이제 kubectl에서 각종 커맨드를 쓸 때 --subresource를 사용하는 게 GA가 됐다!

kubectl patch nodes worker1 --subresource='status' --type='json' -p='[{"op": "add", "path": "/status/capacity/custom.resource~1aaa", "value":"10"}]'

이전에 7W - 쿠버네티스의 스케줄링, 커스텀 스케줄러 설정#사전 세팅을 하다가 알게 된 기능인데, 이걸 이용하면 원래는 api 서버에서 전적으로 관리하는 리소스의 status 부분을 수정하는 게 가능해진다..!
노드에 커스텀 자원을 추가할 때 유용하게 썼는데, 앞으로 단순하게 apply로는 적용되지 않았던 다양한 필드를 커스텀하는데 활용될 수 있을 것 같다.
(좋은 방식인지는 모르겠다만, 유용한 구석은 있을 것으로 생각한다.)

서비스 IP 할당 로직이 새롭게 개편됐다.
원래 서비스 IP는 클러스터 생성 시에 CIDR를 정해서 생성한다.
서비스가 점차 많아지며 이 대역의 여유분이 부족해지면 api 서버에 설정을 넣어 재기동하거나 하는 등의 방식으로 대응해야만 했다.
그러나 이제는 ServiceCIDR, IPAddress라는 리소스를 활용해 클러스터 차원에서 동적으로 서비스 대역을 넓힐 수 있다.

apiVersion: networking.k8s.io/v1beta1
kind: ServiceCIDR
metadata:
  name: newcidr1
spec:
  cidrs:
  - 10.96.0.0/24

이런 식으로 cidr 리소스를 만들어 넣어주면 이게 클러스터의 서비스 대역으로 추가되는 방식이다.
해당 cidr로부터 ip 주소를 받은 서비스가 생기면 IpAddress라는 리소스가 생기며, 어떤 ip를 받았고 어떤 서비스가 이걸 가지고 있는지 확인할 수 있다.
그리고 IpAddress가 있는 동안 ServiceCIDR 리소스에는 파이널라이저가 세팅되어 의존성이 해소되기 전까지 삭제되지 않도록 보장된다.

개인적으로는 IpAddress 리소스가 디버깅에 도움을 줄 수 있을 것 같다.
특정 IP를 통해 이를 활용하는 서비스를 추적하는 방향이 가능해지기 때문이다.
(kubectl get svc -A | grep {ip} 로 해도 되긴 하다 ㅋ)

kube-proxy에서 nftables 모드가 GA가 됐다.
호환성 문제가 있을 수 있기에 아직 iptables 모드가 기본값으로 세팅되지만, nftables가 속도와 리소스 효율에서 성능이 검증됐으니 사용해보는 것도 좋을 것 같다.
nftables의 장점은 이 문서에 자세히 정리돼있다.[3]

토폴로지 기반 라우팅, 트래픽 분산 기능이 GA가 됐다.
이를 통해 여러 가용 영역을 둔 클러스터에서 트래픽을 쿠버네티스 네이티브하게 최적화하는데 도움이 될 것으로 생각된다.
기본적으로 토폴로지 기반 힌트가 엔드포인트슬라이스에 설정되며, 이때 서비스 스펙에 trafficDistribution: PreferClose를 통해 가능한 트래픽이 같은 영역으로 가도록 유도할 수 있다.
이전에는 service.kubernetes.io/topology-mode: Auto 어노테이션을 달아서 이런 것을 유도할 수 있었는데, 이때는 각 영역 별 리소스 값을 기반으로 트래픽을 분산했다.
그러나 trafficDistribution은 조금 더 방식이 명확하다.
일단 같은 영역으로 보내는 것을 무조건 선호하지만, 같은 영역에 엔드포인트가 없다면 그때 다른 영역으로 트래픽을 보내는 방식이다.[4]
각 영역의 엔드포인트 개수를 기반으로 트래픽을
topology-aware 라우팅과 트래픽 분산 기능이 GA(General Availability)

CPU Manager에 SMT(Simultaneous Multithreading) 구성에 맞지 않는 워크로드를 거부할 수 있도록 하는 정책 옵션이 추가된다.
이제 파드가 한 CPU 코어를 독점하고자 할 때, 하위 스레드까지 해당 코어에 할당되도록 강제할 수 있다.
이를 통해 의도하지 않게 워크로드가 CPU 자원을 공유하는 상황을 방지할 수 있다.
kubelet을 세팅할 시 --cpu-manager-policy=static으로 설정하면 QoS에 따라 cpu 자원의 독점을 설정할 수 있다.[5] [6]
이때 스레드까지 한 코어에 몰빵하게 함으로써 의도된 대로 자원이 사용될 수 있게 보장할 수 있다는 것.

어피니티에서 matchLabelKeys, mismatchLabelKeys 필드가 GA가 된다.
기본적으로 특정 키를 설정하면 해당 키가 라벨 셀렉터로 들어가는 식으로 동작하는데, 디플로이먼트 같은 버전을 가진 워크로드에서 버전 별 어피니티 설정을 하고자 할 때 유용하다.
matchLabelKeys 참고.

토폴로지 분산 제약에서 테인트, 어피니티의 정보를 활용할지 설정할 수 있다.
기본적으로 이게 설정돼있긴 한데, 이걸 무시하는 설정도 가능하게 됐다는 것.

근데 토폴 분산 세팅할 때 테인트를 무시하게 하는 운영 케이스가.. 얼마나 있으려나..?

볼륨 포퓰레이터(볼륨 기입자..?)가 GA가 된다.
PVC를 복제하거나 스냅샷을 이용해서 PVC를 마운팅하기 전에 내용물을 초기화하는 것이 가능한데, 이 방식을 조금 더 일반화시켜 다양한 소스로부터 볼륨의 내용물을 채울 수 있게 된 것이다.
dataSourceRef 필드를 이용하면 된다.
이 동작은 volume-data-source-validator라는 컨트롤러가 수행한다.
VolumePopulator라는 CRD도 추가돼서 이에 맞춰진 플러그인을 사용에 원하는 데이터 소스 유형을 등록해 사용할 수 있을 것으로 기대된다.

PV가 PVC보다 먼저 지워지는 경우 Delete 회수 정책(reclaim policy)이 제대로 적용되지 않는 이슈가 있었다.
(실제 스토리지 자원이 사라지지 않았다는 것.)
이제 PV에는 PVC에 대한 파이널라이저가 세팅되어 PVC가 지워지기 전까지 지워지지 않는 것이 보장된다.

근데 파이널라이저 세팅되는 건 문서에서도 보고 실습할 때도 많이 봐서 너무 당연하게 그런 줄 알고 있었는데, 알파 단계가 길었던 것인가 싶기도 하다.

Recursive ReadOnly Mount

이건 별도의 언급은 없었는데, 하위 리스트에서 발견해서 이쪽으로 올렸다.
1.32에서서도 피쳐게이트를 활성화하면 사용할 수 있었던 기능으로, 이를 지원하는 CRI를 필요로 한다.
Containerd의 경우 2.0.0 버전 이상을 사용해야많 활용할 수 있다.
E-파드 마운팅 recursiveReadOnly에서 실습 실패한 경험이 있다.

베타로 전환되는 기능

로드밸런서로 라우팅된 트래픽의 응답이 로드밸런서을 거치지 않고 클라이언트로 반환되는 기능이 윈도우 kube-proxy에 지원된다고 한다.
윈도우는 친숙하지 않아 건너뛴다..

구조화된 파라미터는 DRA의 핵심 부분 중 하나로, resource.k8s.io/v1beta2 버전으로 등록된다고 한다.
kubelet에서는 버전 변경에 대해 DRA의 리소스들이 재생성되지 않고 변경이 이뤄질 수 있도록 지원한다.
추가적으로 드라이버를 등록 해제 할 때 30초의 유예 기간을 주어 드라이버가 롤링 업데이트를 수행하지 않아도 된다.

지속적으로 DRA에 대한 업데이트가 빠르게 적용되고 있는데, 아무래도 GPU 자원이 중요한 ML 환경을 위한 지원을 최대한 빠르게 적용하려는 의도가 느껴진다.
GPU나 고속 네트워크 인터페이스와 같은 자원들을 클러스터에서 자유롭게 활용할 수 있도록 하는 정교한 인터페이스가 지원된다는 것은 앞으로 쿠버네티스 클러스터를 다양한 방식으로 활용하는데 큰 도움을 줄 것 같다.

위와 마찬가지로 DRA에 대한 기능이다.
이제 네트워크 인터페이스 자원을 조금 더 쿠버네티스 네트워크 환경에 통합하기 용이해질 것으로 기대된다.

kube-scheduler는 활성 큐(active queue)에서 생성 요청이 들어온 파드를 꺼내와 스케줄링을 진행한다.
간혹 이 큐에 오류로 인해 등록되지 않은 파드들이 있는데, 이제 스케줄러는 활성 큐가 비어있을 때 backoff queue에서 이들을 꺼내서 스케줄링을 진행한다.

선점(preemption)은 중요도가 높은 파드가 낮은 파드를 노드로부터 축출시키고 배치될 수 있도록 하는 기법이다.
스케줄러는 이 작업을 해당 노드의 파드 삭제가 완료되고 나서야 선점 파드를 배치시키는 식으로 진행한다.
이제는 파드 삭제 요청을 날린 후 삭제 완료 여부를 기다리지 않고 비동기적으로 선점 파드를 배치시킨다.
스케줄러 단에서는 이미 요청을 전부 수행한 상태이니 해당 파드들의 정보를 읽어 제대로 노드에 반영하는 것은 이제 순전히 kubelet의 몫이 될 것이다.

ClusterTrustBundle은 클러스터 전역적으로 X.509 인증서 묶음을 관리하기 위한 리소스로, 이번 버전에서 베타가 된다.
이미 Cert Manager를 주로 활용하는 현 운영 환경에서 이 리소스가 얼마나 유용하게 쓰일 수 있을지 잘 모르겠다.
어쩌면 cert manager가 이 리소스를 활용하여 기능을 제공하는 방향으로 업데이트가 이뤄지지 않을까 하는 생각이 든다.

SupplementalGroupsPolicy 피처 게이트를 활성화 하면 파드의 시큐리티 컨텍스트에 그룹 정책을 조금 더 세밀하게 제어할 수 있게 된다.
기본적으로는 파드 스펙에 명시한 내용과 컨테이너 내부의 /etc/group 파일의 내용을 병합하는 식으로 설정이 되는데, 이제는 아예 컨테이너의 파일을 무시하고 파드 스펙에 명시한대로만 설정되도록 고정할 수 있다.

OCI 이미지를 파드에 볼륨으로 사용할 수 있다.
image volume 참고.

2016년부터 제안됐던, 유저 네임스페이스에서 실행되는 파드 기능이 기본 활성화된다.
(이전에도 베타였으나 이번에는 기본값이 활성화라는 점이 다르다.)
파드 스펙에 .spec.hostUsers를 사용하지 않는 조직에서는 신경 쓸 사항은 아니다.

1.12 버전에서 알파도 등록됐던 파드 필드인데, 1.31에 기본 비활성화 상태로 베타로 등록됐고 이제 기본 활성화로 변경된다.
이건 파드의 /proc 파일시스템, 즉 프로세스 관련한 사항을 유저가 커스텀할 수 있도록 하여 파드를 보다 정제된 형태로 고립시킬 수 있게 돕는다.
이 기능은 유저네임스페이스에서 파드를 운용할 때 유용하다.
보통의 CRI는 컨테이너를 제한적으로 /proc 마운팅하는 기능을 제공하는데, 권한 없는 파드에서 중첩된 형태로 컨테이너를 실행시키기 위해서는 이 제한을 완화시킬 필요가 있다고 한다.
이럴 때 이 기능이 유용하다.

유저 네임스페이스 파드를 사용해본 적이 없어서 사실 이 부분은 완벽하게 이해하진 못 했다.

CPU 매니저 정책에서 NUMA(Non-Uniform Memroy Access) 정책이 추가된다.
NUMA는 각 CPU 프로세서 별로 물리적으로 가까운 메모리 영역을 할당해 cpu의 캐시 미스를 줄여 성능을 높이는 설계 방법이다.[7]
(내게는 생소한 개념이라 틀릴 수 있다.)
이 정책은 여러 CPU로 리소스 할당이 분할되도록 해서 NUMA를 활용하는 시스템에서 성능을 개선한다.

파드의 preStop 라이프사이클 훅에 sleep 액션이 있다.
이게 원래는 0초를 설정하면 검증 에러가 났는데, 이제 기본적으로 지원하도록 바뀐다.
이 방식은 프리스탑 훅이 필요하긴 한데 지연이 필요하지 않은 경우 유용할 것이다.

오브젝트 변경과 검증을 하는 새로운 내부 매커니즘을 도입한다!
validation-gen은 쿠버네티스 컨트리뷰터가 선언적인 검증 규칙을 생성할 수 있도록 도와주는 내부 툴이다.
이는 쿠버 개발자가 검증 조건을 선언적으로 정의할 수 있게 해서 API 검증을 조금 더 견고하게, 유지보수가 용이하게 하여 일관성을 보장할 수 있도록 돕는다.

알파로 추가되는 기능

알파 기능들은 대체로 실제 스테이블이 되기까지 시간이 오래 걸리고 기능 변경도 많이 일어나므로 간략하게만 설명한다.

HPA에서 메트릭의 작은 변화는 별도의 계산과 수정 없이 용인할 수 있도록 하는 설정을 추가한다.

크룹백이 일어날 때 재시작 딜레이를 커스텀할 수 있게 만든다.

기본적으로 컨테이너의 종료 시그널은 기반이 된 이미지의 설정에만 의존했다.
ContainerStopSignals 피쳐게이트를 사용하면 이제 종료 시그널을 커스텀할 수 있게 된다.

DRA 관련 알파로 도입된 피처 게이트 목록

이미지가 이미 노드에 있더라도, kubelet은 이미지 풀 관련 인증 정보의 업데이트가 일어났을 때 인증 체크를 수행해야 한다.

노드의 토폴로지 라벨 정보가 Downward API로 접근된다.
이건 좋아 보이긴 하는데?
AWS로 치면 IMDS 없이 노드 정보를 확인할 수 있게 되니 애드온 설정 시 정적으로 노드를 정해두고 활용하던 전략에 유연성을 부여할 수 있지 않을까?

파드의 metadata.generation 필드는 사용되지 않았다.
이제 status.observedGeneration를 통해 etcd내의 파드의 생성 시점이나 시기를 조금 더 투명하게 볼 수 있게 된다.

kubelet의 CPU Manager는 L3 캐시(LLC, Last Level Cache) 아키텍처를 인식하지 못했다.
그래서 CPU 할당 시 이를 고려하지 않고 배치해 성능 저하나 시끄러운 이웃 문제를 일으킬 수 있었다.
이 기능은 CPU Manager가 L3 캐시 분할 구조를 인지하고 CPU 코어를 더 적절하게 할당하도록 개선한다.

L3 캐시는 여러 코어가 공유하는 구조인데, 그래도 코어 그룹 별로 분할되어 있어 이 레이어를 명확히 인지하는 것이 캐싱을 고려한 자원 배치에 유용할 것으로 기대된다.

리눅스에서 cgroup v2로 PSI 통계와 메트릭을 제공한다.
Pressure Stall Information은 리소스 부족으로 인해 작업이 지연되거나 멈춘 정도를 측정하는 기능이라고 한다.
태스크 단위로 시간 비율을 계산해준다고 한다.

kubelet이 이미지를 받을 때 서비스 어카운트의 토큰을 이용할 수 있다.
이건 스테이블에서 언급된 노드 바인딩 서비스 어카운트 토큰과 연계되어 개발되고 있는 기능으로 보인다.

제거되는 기능

엔드포인트슬라이스이 기본이 됨에 따라, 기존 엔드포인트 api는 deprecated된다.
마이그레이션 가이드가 제공되고 있다.[8]
근데 직접적으로 엔드포인트 리소스를 만들어 관리하던 조직이 아니라면 신경쓸 바는 아니다.

노드 status에 kube proxy 버전 정보가 사라진다.
해당 정보는 제대로 일치하지 않는 경우가 많았다고 한다.
이제 해당 정보를 얻으려면 노드에 들어가서 까봐야 하나..?

Kubernetes v1.31 - Elli에 거의 완료됐던 내장 볼륨의 잔재 정도랄까..?
깃레포 볼륨도 삭제!
깃레포를 가져오는 방법은 초기화 컨테이너나 깃 싱크같은 다른 대안이 많다.
현재는 아직까지 해당 방식을 사용할 수는 있으나, 1.39 버전에서는 완전히 제거될 것이라고 한다.

윈도우 파드에서 호스트 네트워크를 쓸 수 없게 된다.

관련 문서

이름 noteType created
Kubernetes v1.31 - Elli knowledge 2024-08-15
Kubernetes v1.32 - Penelope knowledge 2024-12-17
Kubernetes v1.33 - Octarine knowledge 2025-04-25

참고


  1. https://en.wikipedia.org/wiki/Discworld_(world) ↩︎

  2. https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.7 ↩︎

  3. https://kubernetes.io/blog/2025/02/28/nftables-kube-proxy/ ↩︎

  4. https://kubernetes.io/docs/reference/networking/virtual-ips/#comparison-with-service-kubernetes-io-topology-mode-auto ↩︎

  5. https://kubernetes.io/docs/tasks/administer-cluster/cpu-management-policies/ ↩︎

  6. https://kubernetes.io/docs/concepts/policy/node-resource-managers/#policies-for-assigning-cpus-to-pods ↩︎

  7. https://ko.wikipedia.org/wiki/불균일_기억_장치_접근 ↩︎

  8. https://kubernetes.io/blog/2025/04/24/endpoints-deprecation/ ↩︎